home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / languags / cdecl.1 < prev    next >
Text File  |  1988-11-05  |  60KB  |  2,363 lines

  1. Path: wucfua!wucs1!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!ucbvax!husc6!bbn!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i054:  cdecl - C & C++ declaration composer/decoder, Part01/03
  5. Message-ID: <10053@swan.ulowell.edu>
  6. Date: 4 Nov 88 23:08:26 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2351
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: finkel@taurus.bitnet (Udi Finkelstein)
  12. Posting-number: Volume 2, Issue 54
  13. Archive-name: languages/cdecl.1
  14.  
  15. Cdecl is a program for encoding and decoding ANSI C (C++) type-declarations.
  16.  
  17. #    This is a shell archive.
  18. #    Remove everything above and including the cut line.
  19. #    Then run the rest of the file through sh.
  20. #----cut here-----cut here-----cut here-----cut here----#
  21. #!/bin/sh
  22. # shar:    Shell Archiver
  23. #    Run the following text with /bin/sh to create:
  24. #    cdecl.c
  25. #    cdgram.y
  26. #    cdecl.1
  27. # This archive created: Fri Nov  4 18:00:14 1988
  28. cat << \SHAR_EOF > cdecl.c
  29. /*
  30.  * cdecl - ANSI C and C++ declaration composer & decoder
  31.  *
  32.  *    originally written
  33.  *        Graham Ross
  34.  *        once at tektronix!tekmdp!grahamr
  35.  *        now at Context, Inc.
  36.  *
  37.  *    modified to provide hints for unsupported types
  38.  *    added argument lists for functions
  39.  *    added 'explain cast' grammar
  40.  *    added #ifdef for 'create program' feature
  41.  *        ???? (sorry, I lost your name and login)
  42.  *
  43.  *    conversion to ANSI C
  44.  *        David Wolverton
  45.  *        ihnp4!houxs!daw
  46.  *
  47.  *    merged D. Wolverton's ANSI C version w/ ????'s version
  48.  *    added function prototypes
  49.  *    added C++ declarations
  50.  *    made type combination checking table driven
  51.  *    added checks for void variable combinations
  52.  *    made 'create program' feature a runtime option
  53.  *    added file parsing as well as just stdin
  54.  *    added help message at beginning
  55.  *    added prompts when on a TTY or in interactive mode
  56.  *    added getopt() usage
  57.  *    added -a, -r, -p, -c, -d, -D, -V, -i and -+ options
  58.  *    delinted
  59.  *    added #defines for those without getopt or void
  60.  *    added 'set options' command
  61.  *    added 'quit/exit' command
  62.  *    added synonyms
  63.  *        Tony Hansen
  64.  *        attmail!tony, ihnp4!pegasus!hansen
  65.  *
  66.  *    added extern, register, static
  67.  *    added links to explain, cast, declare
  68.  *    separately developed ANSI C support
  69.  *        Merlyn LeRoy
  70.  *        merlyn@rose3.rosemount.com
  71.  *
  72.  *    merged versions from LeRoy
  73.  *    added tmpfile() support
  74.  *    allow more parts to be missing during explanations
  75.  *        Tony Hansen
  76.  *        attmail!tony, ihnp4!pegasus!hansen
  77.  */
  78.  
  79. char cdeclsccsid[] = "@(#)cdecl.c    2.4 3/31/88";
  80.  
  81. #include <stdio.h>
  82. #include <ctype.h>
  83. #ifdef AMIGA
  84.  
  85. char *strcat(), *strncat(), *strcpy(), *strncpy(), index(), rindex();
  86. char *strchr(), *strrchr(), *strpbrk(), *strtok();
  87. int strcmp(), strncmp(), strlen(), strspn(), strcspn();
  88.  
  89. char *malloc();
  90. extern free(), exit(), perror();
  91.  
  92. #include <errno.h>
  93. #else /* AMIGA not defined */
  94. #if __STDC__ || defined(DOS)
  95. # include <stdlib.h>
  96. # include <stddef.h>
  97. # include <string.h>
  98. # include <stdarg.h>
  99. #else
  100. # ifndef NOVARARGS
  101. #  include <varargs.h>
  102. # endif /* ndef NOVARARGS */
  103. char *malloc();
  104. void free(), exit(), perror();
  105. # ifdef BSD
  106. #  include <strings.h>
  107.    extern int errno;
  108. #  define strrchr rindex
  109. #  define NOTMPFILE
  110. # else
  111. #  include <string.h>
  112. #  include <errno.h>
  113. # endif /* BSD */
  114. # ifdef NOVOID
  115. #  define void int
  116. # endif /* NOVOID */
  117. #endif /* __STDC__ || DOS */
  118.  
  119. #endif /* AMIGA */
  120.  
  121. #define    MB_SHORT    0001
  122. #define    MB_LONG        0002
  123. #define    MB_UNSIGNED    0004
  124. #define MB_INT        0010
  125. #define MB_CHAR        0020
  126. #define MB_FLOAT    0040
  127. #define MB_DOUBLE    0100
  128. #define MB_VOID        0200
  129. #define    MB_SIGNED    0400
  130.  
  131. #define NullCP ((char*)NULL)
  132. #ifdef dodebug
  133. # define Debug(x) do { if (DebugFlag) (void) fprintf x; } while (0)
  134. #else
  135. # define Debug(x) /* nothing */
  136. #endif
  137.  
  138. #if __STDC__
  139.   char *ds(char *), *cat(char *, ...), *visible(int);
  140.   int getopt(int,char **,char *);
  141.   int main(int, char **);
  142.   int yywrap(void);
  143.   int dostdin(void);
  144.   void mbcheck(void), dohelp(void), usage(void);
  145.   void prompt(void), doprompt(void), noprompt(void);
  146.   void unsupp(char *, char *);
  147.   void notsupported(char *, char *, char *);
  148.   void yyerror(char *);
  149.   void doset(char *);
  150.   void dodeclare(char*, char*, char*, char*, char*);
  151.   void docast(char*, char*, char*, char*);
  152.   void dodexplain(char*, char*, char*, char*);
  153.   void docexplain(char*, char*, char*, char*);
  154.   void setprogname(char *);
  155.   int dotmpfile(int, char**), dofileargs(int, char**);
  156. #else
  157.   char *ds(), *cat(), *visible();
  158.   int getopt();
  159.   void mbcheck(), dohelp(), usage();
  160.   void prompt(), doprompt(), noprompt();
  161.   void unsupp(), notsupported();
  162.   void yyerror();
  163.   void doset(), dodeclare(), docast(), dodexplain(), docexplain();
  164.   void setprogname();
  165.   int dotmpfile(), dofileargs();
  166. #endif /* __STDC__ */
  167.   FILE *tmpfile();
  168.  
  169. /* variables used during parsing */
  170. unsigned modbits = 0;
  171. int arbdims = 1;
  172. char *savedname = 0;
  173. char unknown_name[] = "unknown_name";
  174. char prev = 0;        /* the current type of the variable being examined */
  175.             /*    values    type                   */
  176.             /*    p    pointer                   */
  177.             /*    r    reference               */
  178.             /*    f    function               */
  179.             /*    a    array (of arbitrary dimensions)    */
  180.             /*    A    array with dimensions           */
  181.             /*    n    name                   */
  182.             /*    v    void                   */
  183.             /*    s    struct | class               */
  184.             /*    t    simple type (int, long, etc.)       */
  185.  
  186. /* options */
  187. int RitchieFlag = 0;        /* -r, assume Ritchie PDP C language */
  188. int MkProgramFlag = 0;        /* -c, output {} and ; after declarations */
  189. int PreANSIFlag = 0;        /* -p, assume pre-ANSI C language */
  190. int CplusplusFlag = 0;        /* -+, assume C++ language */
  191. int OnATty = 0;            /* stdin is coming from a terminal */
  192. int Interactive = 0;        /* -i, overrides OnATty */
  193. int KeywordName = 0;        /* $0 is a keyword (declare, explain, cast) */
  194. char *progname = "cdecl";    /* $0 */
  195.  
  196. #if dodebug
  197. int DebugFlag = 0;        /* -d, output debugging trace info */
  198. #endif
  199.  
  200. #ifdef doyydebug        /* compile in yacc trace statements */
  201. #define YYDEBUG 1
  202. #endif /* doyydebug */
  203.  
  204. #include "cdgram.c"
  205. #include "cdlex.c"
  206.  
  207. /* definitions (and abbreviations) for type combinations cross check table */
  208. #define ALWAYS    0    /* combo always okay */
  209. #define _    ALWAYS
  210. #define NEVER    1    /* combo never allowed */
  211. #define X    NEVER
  212. #define RITCHIE    2    /* combo not allowed in Ritchie compiler */
  213. #define R    RITCHIE
  214. #define PREANSI    3    /* combo not allowed in Pre-ANSI compiler */
  215. #define P    PREANSI
  216. #define ANSI    4    /* combo not allowed anymore in ANSI compiler */
  217. #define A    ANSI
  218.  
  219. /* This is an lower left triangular array. If we needed */
  220. /* to save 9 bytes, the "long" row can be removed. */
  221. char crosscheck[9][9] = {
  222.     /*            L, I, S, C, V, U, S, F, D, */
  223.     /* long */        _, _, _, _, _, _, _, _, _,
  224.     /* int */        _, _, _, _, _, _, _, _, _,
  225.     /* short */        X, _, _, _, _, _, _, _, _,
  226.     /* char */        X, X, X, _, _, _, _, _, _,
  227.     /* void */        X, X, X, X, _, _, _, _, _,
  228.     /* unsigned */    R, _, R, R, X, _, _, _, _,
  229.     /* signed */    P, P, P, P, X, X, _, _, _,
  230.     /* float */        A, X, X, X, X, X, X, _, _,
  231.     /* double */    P, X, X, X, X, X, X, X, _
  232. };
  233.  
  234. /* the names and bits checked for each row in the above array */
  235. struct
  236.     {
  237.     char *name;
  238.     int bit;
  239.     } crosstypes[9] =
  240.     {
  241.         { "long",        MB_LONG        },
  242.         { "int",        MB_INT        },
  243.         { "short",        MB_SHORT    },
  244.         { "char",        MB_CHAR        },
  245.         { "void",        MB_VOID        },
  246.         { "unsigned",    MB_UNSIGNED    },
  247.         { "signed",        MB_SIGNED    },
  248.         { "float",        MB_FLOAT    },
  249.         { "double",        MB_DOUBLE    }
  250.     };
  251.  
  252. /* Run through the crosscheck array looking */
  253. /* for unsupported combinations of types. */
  254. void mbcheck()
  255. {
  256.     register int i, j, restrict;
  257.     char *t1, *t2;
  258.  
  259.     /* Loop through the types */
  260.     /* (skip the "long" row) */
  261.     for (i = 1; i < 9; i++)
  262.     {
  263.     /* if this type is in use */
  264.     if ((modbits & crosstypes[i].bit) != 0)
  265.         {
  266.         /* check for other types also in use */
  267.         for (j = 0; j < i; j++)
  268.         {
  269.         /* this type is not in use */
  270.         if (!(modbits & crosstypes[j].bit))
  271.             continue;
  272.         /* check the type of restriction */
  273.         restrict = crosscheck[i][j];
  274.         if (restrict == ALWAYS)
  275.             continue;
  276.         t1 = crosstypes[i].name;
  277.         t2 = crosstypes[j].name;
  278.         if (restrict == NEVER)
  279.             {
  280.             notsupported("", t1, t2);
  281.             }
  282.         else if (restrict == RITCHIE)
  283.             {
  284.             if (RitchieFlag)
  285.             notsupported(" (Ritchie Compiler)", t1, t2);
  286.             }
  287.         else if (restrict == PREANSI)
  288.             {
  289.             if (PreANSIFlag || RitchieFlag)
  290.             notsupported(" (Pre-ANSI Compiler)", t1, t2);
  291.             }
  292.         else if (restrict == ANSI)
  293.             {
  294.             if (!RitchieFlag && !PreANSIFlag)
  295.             notsupported(" (ANSI Compiler)", t1, t2);
  296.             }
  297.         else
  298.             {
  299.             (void) fprintf (stderr,
  300.             "%s: Internal error in crosscheck[%d,%d]=%d!\n",
  301.             progname, i, j, restrict);
  302.             exit(1); /* NOTREACHED */
  303.             }
  304.         }
  305.         }
  306.     }
  307. }
  308.  
  309. /* undefine these as they are no longer needed */
  310. #undef _
  311. #undef ALWAYS
  312. #undef X
  313. #undef NEVER
  314. #undef R
  315. #undef RITCHIE
  316. #undef P
  317. #undef PREANSI
  318. #undef A
  319. #undef ANSI
  320.  
  321. /* Write out a message about something */
  322. /* being unsupported, possibly with a hint. */
  323. void unsupp(s,hint)
  324. char *s,*hint;
  325. {
  326.     notsupported("", s, NullCP);
  327.     if (hint)
  328.     (void) fprintf(stderr, "\t(maybe you mean \"%s\")\n", hint);
  329. }
  330.  
  331. /* Write out a message about something */
  332. /* being unsupported on a particular compiler. */
  333. void notsupported(compiler, type1, type2)
  334. char *compiler, *type1, *type2;
  335. {
  336.     if (type2)
  337.     (void) fprintf(stderr,
  338.         "Warning: Unsupported in%s C%s -- '%s' with '%s'\n",
  339.         compiler, CplusplusFlag ? "++" : "", type1, type2);
  340.     else
  341.     (void) fprintf(stderr,
  342.         "Warning: Unsupported in%s C%s -- '%s'\n",
  343.         compiler, CplusplusFlag ? "++" : "", type1);
  344. }
  345.  
  346. /* Called by the yacc grammar */
  347. void yyerror(s)
  348. char *s;
  349. {
  350.     (void) printf("%s\n",s);
  351.     Debug((stdout, "yychar=%d\n", yychar));
  352. }
  353.  
  354. /* Called by the yacc grammar */
  355. int yywrap()
  356. {
  357.     return 1;
  358. }
  359.  
  360. /*
  361.  * Support for dynamic strings:
  362.  * cat() creates a string from the concatenation
  363.  * of a null terminated list of input strings.
  364.  * The input strings are free()'d by cat()
  365.  * (so they better have been malloc()'d).
  366.  *
  367.  * the different methods of <stdarg.h> and
  368.  * <vararg.h> are handled within these macros
  369.  */
  370. #ifdef AMIGA
  371. # define VA_DCL(type,var)        (var) type var;
  372. # define VA_START(list,var,type)    (list = (va_list)&(var) , (var))
  373. # define va_arg(list,type)        ((type *)(list += sizeof(type)))[0]
  374. # define va_end(p)            /* nothing */
  375. typedef char *va_list;
  376. #else
  377. #if __STDC__
  378. #  define VA_DCL(type,var)        (type var,...)
  379. #  define VA_START(list,var,type)    ((va_start(list,var)) , (var))
  380. #else
  381. #if defined(DOS)
  382. #  define VA_DCL(type,var)        (var,...) type var;
  383. #  define VA_START(list,var,type)    ((va_start(list,var)) , (var))
  384. #else
  385. #ifndef NOVARARGS
  386. # define VA_DCL(type,var)        (va_alist) va_dcl
  387. # define VA_START(list,var,type)    ((va_start(list)) , va_arg(list,type))
  388. #else
  389.    /*
  390.     *    it is assumed here that machines which don't have either
  391.     *    <varargs.h> or <stdarg.h> will put its arguments on
  392.     *    the stack in the "usual" way and consequently can grab
  393.     *    the arguments using the "take the address of the first
  394.     *    parameter and increment by sizeof" trick.
  395.     */
  396. # define VA_DCL(type,var)        (var) type var;
  397. # define VA_START(list,var,type)    (list = (va_list)&(var) , (var))
  398. # define va_arg(list,type)        ((type *)(list += sizeof(type)))[-1]
  399. # define va_end(p)            /* nothing */
  400. typedef char *va_list;
  401. #endif /* NOVARARGS */
  402. #endif /* DOS */
  403. #endif /* __STDC__ */
  404. #endif /* AMIGA */
  405.  
  406. /* VARARGS */
  407. char *cat
  408. VA_DCL(char*, s1)
  409. {
  410.     register char *newstr;
  411.     register unsigned len = 1;
  412.     char *str;
  413.     va_list args;
  414.  
  415.     /* find the length which needs to be allocated */
  416.     str = VA_START(args, s1, char*);
  417.     for ( ; str; str = va_arg(args, char*))
  418.     len += strlen(str);
  419.     va_end(args);
  420.  
  421.     /* allocate it */
  422.     newstr = malloc(len);
  423.     if (newstr == 0)
  424.     {
  425.     (void) fprintf (stderr, "%s: out of malloc space within cat()!\n",
  426.         progname);
  427.     exit(1);
  428.     }
  429.     newstr[0] = '\0';
  430.  
  431.     /* copy in the strings */
  432.     str = VA_START(args, s1, char*);
  433.     for ( ; str; str = va_arg(args, char*))
  434.     {
  435.     (void) strcat(newstr,str);
  436.     free(str);
  437.     }
  438.     va_end(args);
  439.  
  440.     Debug((stderr, "\tcat created '%s'\n", newstr));
  441.     return newstr;
  442. }
  443.  
  444. /*
  445.  * ds() makes a malloc()'d string from one that's not.
  446.  */
  447. char *ds(s)
  448. char *s;
  449. {
  450.     register char *p = malloc((unsigned)(strlen(s)+1));
  451.  
  452.     if (p)
  453.     (void) strcpy(p,s);
  454.     else
  455.     {
  456.     (void) fprintf (stderr, "%s: malloc() failed!\n", progname);
  457.     exit(1);
  458.     }
  459.     return p;
  460. }
  461.  
  462. /* return a visible representation of a character */
  463. char *visible(c)
  464. int c;
  465. {
  466.     static char buf[5];
  467.  
  468.     c &= 0377;
  469.     if (isprint(c))
  470.     {
  471.     buf[0] = c;
  472.     buf[1] = '\0';
  473.     }
  474.     else
  475.     (void) sprintf(buf,"\\%03o",c);
  476.     return buf;
  477. }
  478.  
  479. #ifdef NOTMPFILE
  480. /* provide a conservative version of tmpfile() */
  481. /* for those systems without it. */
  482. /* tmpfile() returns a FILE* of a file opened */
  483. /* for read&write. It is supposed to be */
  484. /* automatically removed when it gets closed, */
  485. /* but here we provide a separate rmtmpfile() */
  486. /* function to perform that function. */
  487. /* Also provide several possible file names to */
  488. /* try for opening. */
  489. static char *file4tmpfile = 0;
  490.  
  491. FILE *tmpfile()
  492. {
  493.  
  494. #ifdef AMIGA
  495.     static char *listtmpfiles[] =
  496.     {
  497.     ":T/cdeclXXXXXX",
  498.     "ram:cdeclXXXXXX",
  499.     "ram:cdeclXXXXXX",
  500.     "ram:cdeclXXXXXX",
  501.     0
  502.     };
  503. #else
  504.     static char *listtmpfiles[] =
  505.     {
  506.     "/usr/tmp/cdeclXXXXXX",
  507.     "/tmp/cdeclXXXXXX",
  508.     "/cdeclXXXXXX",
  509.     "cdeclXXXXXX",
  510.     0
  511.     };
  512. #endif
  513.  
  514.     char **listp = listtmpfiles;
  515.     for ( ; *listp; listp++)
  516.     {
  517.     FILE *retfp;
  518.     (void) mktemp(*listp);
  519.     retfp = fopen(*listp, "w+");
  520.     if (!retfp)
  521.         continue;
  522.     file4tmpfile = *listp;
  523.     return retfp;
  524.     }
  525.  
  526.     return 0;
  527. }
  528.  
  529. void rmtmpfile()
  530. {
  531.     if (file4tmpfile)
  532.     (void) unlink(file4tmpfile);
  533. }
  534. #else
  535. /* provide a mock rmtmpfile() for normal systems */
  536. # define rmtmpfile()    /* nothing */
  537. #endif /* NOTMPFILE */
  538.  
  539. #ifndef NOGETOPT
  540. extern int optind;
  541. #else
  542. /* This is a miniature version of getopt() which will */
  543. /* do just barely enough for us to get by below. */
  544. /* Options are not allowed to be bunched up together. */
  545. /* Option arguments are not supported. */
  546. int optind = 1;
  547.  
  548. int getopt(argc,argv,optstring)
  549. char **argv;
  550. char *optstring;
  551. {
  552.     int ret;
  553.     char *p;
  554.  
  555.     if ((argv[optind][0] != '-')
  556. #ifdef DOS
  557.     && (argv[optind][0] != '/')
  558. #endif /* DOS */
  559.     )
  560.     return EOF;
  561.  
  562.     ret = argv[optind][1];
  563.     optind++;
  564.  
  565.     for (p = optstring; *p; p++)
  566.     if (*p == ret)
  567.         return ret;
  568.  
  569.     (void) fprintf (stderr, "%s: illegal option -- %s\n",
  570.     progname, visible(ret));
  571.  
  572.     return '?';
  573. }
  574. #endif
  575.  
  576. /* the help messages */
  577. struct helpstruct
  578.     {
  579.     char *text;    /* generic text */
  580.     char *cpptext;    /* C++ specific text */
  581.     } helptext[] =
  582.     {    /* up-to 23 lines of help text so it fits on (24x80) screens */
  583. /*  1 */{ "[] means optional; {} means 1 or more; <> means defined elsewhere", 0 },
  584. /*  2 */{ "  commands are separated by ';' and newlines", 0 },
  585. /*  3 */{ "command:", 0 },
  586. /*  4 */{ "  declare <name> as <english>", 0 },
  587. /*  5 */{ "  cast <name> into <english>", 0 },
  588. /*  6 */{ "  explain <gibberish>", 0 },
  589. /*  7 */{ "  set or set options", 0 },
  590. /*  8 */{ "  help, ?", 0 },
  591. /*  9 */{ "  quit or exit", 0 },
  592. /* 10 */{ "english:", 0 },
  593. /* 11 */{ "  function [( <decl-list> )] returning <english>", 0 },
  594. /* 12 */{ "  array [<number>] of <english>", 0 },
  595. /* 13 */{ "  [{ const | volatile | noalias }] pointer to <english>",
  596.       "  [{const|volatile}] {pointer|reference} to [member of class <name>] <english>" },
  597. /* 14 */{ "  <type>", 0 },
  598. /* 15 */{ "type:", 0 },
  599. /* 16 */{ "  {[<storage-class>] [{<modifier>}] [<C-type>]}", 0 },
  600. /* 17 */{ "  { struct | union | enum } <name>",
  601.       "  {struct|class|union|enum} <name>" },
  602. /* 18 */{ "decllist: a comma separated list of <name>, <english> or <name> as <english>", 0 },
  603. /* 19 */{ "name: a C identifier", 0 },
  604. /* 20 */{ "gibberish: a C declaration, like 'int *x', or cast, like '(int *)x'", 0 },
  605. /* 21 */{ "storage-class: extern, static, auto, register", 0 },
  606. /* 22 */{ "C-type: int, char, float, double, or void", 0 },
  607. /* 23 */{ "modifier: short, long, signed, unsigned, const, volatile, or noalias",
  608.       "modifier: short, long, signed, unsigned, const, or volatile" },
  609.     { 0, 0 }
  610.     };
  611.  
  612. /* Print out the help text */
  613. void dohelp()
  614. {
  615.     register struct helpstruct *p;
  616.     register char *fmt = CplusplusFlag ? " %s\n" : "\t%s\n";
  617.  
  618.     for (p = helptext; p->text; p++)
  619.     if (CplusplusFlag && p->cpptext)
  620.         (void) printf(fmt, p->cpptext);
  621.     else
  622.         (void) printf(fmt, p->text);
  623. }
  624.  
  625. /* Tell how to invoke cdecl. */
  626. void usage()
  627. {
  628.     (void) fprintf (stderr, "Usage: %s [-r|-p|-a|-+] [-ci%s%s] [files...]\n",
  629.     progname,
  630. #ifdef dodebug
  631.     "d",
  632. #else
  633.     "",
  634. #endif /* dodebug */
  635. #ifdef doyydebug
  636.     "D"
  637. #else
  638.     ""
  639. #endif /* doyydebug */
  640.     );
  641.     (void) fprintf (stderr, "\t-r Check against Ritchie PDP C Compiler\n");
  642.     (void) fprintf (stderr, "\t-p Check against Pre-ANSI C Compiler\n");
  643.     (void) fprintf (stderr, "\t-a Check against ANSI C Compiler%s\n",
  644.     CplusplusFlag ? "" : " (the default)");
  645.     (void) fprintf (stderr, "\t-+ Check against C++ Compiler%s\n",
  646.     CplusplusFlag ? " (the default)" : "");
  647.     (void) fprintf (stderr, "\t-c Create compilable output (include ; and {})\n");
  648.     (void) fprintf (stderr, "\t-i Force interactive mode\n");
  649. #ifdef dodebug
  650.     (void) fprintf (stderr, "\t-d Turn on debugging mode\n");
  651. #endif /* dodebug */
  652. #ifdef doyydebug
  653.     (void) fprintf (stderr, "\t-D Turn on YACC debugging mode\n");
  654. #endif /* doyydebug */
  655.     exit(1);
  656.     /* NOTREACHED */
  657. }
  658.  
  659. /* Manage the prompts. */
  660. static int prompting = 1;
  661.  
  662. void doprompt() { prompting = 1; }
  663. void noprompt() { prompting = 0; }
  664.  
  665. void prompt()
  666. {
  667.     if ((OnATty || Interactive) && prompting) {
  668.     (void) printf("%s> ", progname);
  669.     (void) fflush(stdout);
  670.     }
  671. }
  672.  
  673. /* Save away the name of the program from argv[0] */
  674. void setprogname(argv0)
  675. char *argv0;
  676. {
  677. #ifdef DOS
  678.     char *dot;
  679. #endif /* DOS */
  680.  
  681.     progname = strrchr(argv0, '/');
  682.  
  683. #ifdef DOS
  684.     if (!progname)
  685.     progname = strrchr(argv0, '\\');
  686. #endif /* DOS */
  687.  
  688.     if (progname)
  689.     progname++;
  690.     else
  691.     progname = argv0;
  692.  
  693. #ifdef DOS
  694.     dot = strchr(progname, '.');
  695.     if (dot)
  696.     *dot = '\0';
  697.     for (dot = progname; *dot; dot++)
  698.     *dot = tolower(*dot);
  699. #endif /* DOS */
  700. }
  701.  
  702. /* Run down the list of keywords to see if the */
  703. /* program is being called named as one of them */
  704. /* or the first argument is one of them. */
  705. int namedkeyword(argn)
  706. char *argn;
  707. {
  708.     static char *cmdlist[] =
  709.     {
  710.     "explain", "declare", "cast", "help", "?", "set", 0
  711.     };
  712.  
  713.     /* first check the program name */
  714.     char **cmdptr = cmdlist;
  715.     for ( ; *cmdptr; cmdptr++)
  716.     if (strcmp(*cmdptr, progname) == 0)
  717.         {
  718.         KeywordName = 1;
  719.         return 1;
  720.         }
  721.  
  722.     /* now check $1 */
  723.     for (cmdptr = cmdlist; *cmdptr; cmdptr++)
  724.     if (strcmp(*cmdptr, argn) == 0)
  725.         return 1;
  726.  
  727.     /* nope, must be file name arguments */
  728.     return 0;
  729. }
  730.  
  731. /* Read from standard input, turning */
  732. /* on prompting if necessary. */
  733. int dostdin()
  734. {
  735.     int ret;
  736.     OnATty = isatty(0);
  737.     if (OnATty || Interactive)
  738.     {
  739.     (void) printf("Type `help' or `?' for help\n");
  740.     prompt();
  741.     }
  742.  
  743.     yyin = stdin;
  744.     ret = yyparse();
  745.     OnATty = 0;
  746.     return ret;
  747. }
  748.  
  749. /* Write the arguments into a file */
  750. /* and treat that file as the input. */
  751. int dotmpfile(argc, argv)
  752. int argc;
  753. char **argv;
  754. {
  755.     int ret = 0;
  756.     FILE *tmpfp = tmpfile();
  757.     if (!tmpfp)
  758.     {
  759.     int sverrno = errno;
  760.     (void) fprintf (stderr, "%s: cannot open temp file\n",
  761.         progname);
  762.     errno = sverrno;
  763.     perror(progname);
  764.     return 1;
  765.     }
  766.  
  767.     if (KeywordName)
  768.     if (fputs(progname, tmpfp) == EOF)
  769.         {
  770.         int sverrno;
  771.     errwrite:
  772.         sverrno = errno;
  773.         (void) fprintf (stderr, "%s: error writing to temp file\n",
  774.         progname);
  775.         errno = sverrno;
  776.         perror(progname);
  777.         (void) fclose(tmpfp);
  778.         rmtmpfile();
  779.         return 1;
  780.         }
  781.  
  782.     for ( ; optind < argc; optind++)
  783.     if (fprintf(tmpfp, " %s", argv[optind]) == EOF)
  784.         goto errwrite;
  785.  
  786.     if (putc('\n', tmpfp) == EOF)
  787.     goto errwrite;
  788.  
  789.     rewind(tmpfp);
  790.     yyin = tmpfp;
  791.     ret += yyparse();
  792.     (void) fclose(tmpfp);
  793.     rmtmpfile();
  794.  
  795.     return ret;
  796. }
  797.  
  798. /* Read each of the named files for input. */
  799. int dofileargs(argc, argv)
  800. int argc;
  801. char **argv;
  802. {
  803.     FILE *ifp;
  804.     int ret = 0;
  805.  
  806.     for ( ; optind < argc; optind++)
  807.     if (strcmp(argv[optind], "-") == 0)
  808.         ret += dostdin();
  809.  
  810.     else if ((ifp = fopen(argv[optind], "r")) == NULL)
  811.         {
  812.         int sverrno = errno;
  813.         (void) fprintf (stderr, "%s: cannot open %s\n",
  814.         progname, argv[optind]);
  815.         errno = sverrno;
  816.         perror(argv[optind]);
  817.         ret++;
  818.         }
  819.  
  820.     else
  821.         {
  822.         yyin = ifp;
  823.         ret += yyparse();
  824.         }
  825.  
  826.     return ret;
  827. }
  828.  
  829. /* print out a cast */
  830. void docast(name, left, right, type)
  831. char *name, *left, *right, *type;
  832. {
  833.     int lenl = strlen(left), lenr = strlen(right);
  834.  
  835.     if (prev == 'f')
  836.         unsupp("Cast into function",
  837.             "cast into pointer to function");
  838.     else if (prev=='A' || prev=='a')
  839.         unsupp("Cast into array","cast into pointer");
  840.     (void) printf("(%s%*s%s)%s\n",
  841.         type, lenl+lenr?lenl+1:0,
  842.         left, right, name ? name : "expression");
  843.     free(left);
  844.     free(right);
  845.     free(type);
  846.     if (name)
  847.         free(name);
  848. }
  849.  
  850. /* print out a declaration */
  851. void dodeclare(name, storage, left, right, type)
  852. char *name, *storage, *left, *right, *type;
  853. {
  854.     if (prev == 'v')
  855.         unsupp("Variable of type void",
  856.             "variable of type pointer to void");
  857.  
  858.     if (*storage == 'r')
  859.     switch (prev)
  860.         {
  861.         case 'f': unsupp("Register function", NullCP); break;
  862.         case 'A':
  863.         case 'a': unsupp("Register array", NullCP); break;
  864.         case 's': unsupp("Register struct/class", NullCP); break;
  865.         }
  866.  
  867.     if (*storage)
  868.         (void) printf("%s ", storage);
  869.     (void) printf("%s %s%s%s",
  870.         type, left,
  871.     name ? name : (prev == 'f') ? "f" : "var", right);
  872.     if (MkProgramFlag) {
  873.         if ((prev == 'f') && (*storage != 'e'))
  874.             (void) printf(" { }\n");
  875.         else
  876.             (void) printf(";\n");
  877.     } else {
  878.         (void) printf("\n");
  879.     }
  880.     free(storage);
  881.     free(left);
  882.     free(right);
  883.     free(type);
  884.     if (name)
  885.         free(name);
  886. }
  887.  
  888. void dodexplain(storage, constvol, type, decl)
  889. char *storage, *constvol, *type, *decl;
  890. {
  891.     if (type && (strcmp(type, "void") == 0))
  892.     if (prev == 'n')
  893.         unsupp("Variable of type void",
  894.            "variable of type pointer to void");
  895.     else if (prev == 'a')
  896.         unsupp("array of type void",
  897.            "array of type pointer to void");
  898.     else if (prev == 'r')
  899.         unsupp("reference to type void",
  900.            "pointer to void");
  901.  
  902.     if (*storage == 'r')
  903.     switch (prev)
  904.         {
  905.         case 'f': unsupp("Register function", NullCP); break;
  906.         case 'A':
  907.         case 'a': unsupp("Register array", NullCP); break;
  908.         case 's': unsupp("Register struct/union/enum/class", NullCP); break;
  909.         }
  910.  
  911.     (void) printf("declare %s as ", savedname);
  912.     if (*storage)
  913.         (void) printf("%s ", storage);
  914.     (void) printf("%s", decl);
  915.     if (*constvol)
  916.         (void) printf("%s ", constvol);
  917.     (void) printf("%s\n", type ? type : "int");
  918. }
  919.  
  920. void docexplain(constvol, type, cast, name)
  921. char *constvol, *type, *cast, *name;
  922. {
  923.     if (strcmp(type, "void") == 0)
  924.     if (prev == 'a')
  925.         unsupp("array of type void",
  926.            "array of type pointer to void");
  927.     else if (prev == 'r')
  928.         unsupp("reference to type void",
  929.            "pointer to void");
  930.     (void) printf("cast %s into %s", name, cast);
  931.     if (strlen(constvol) > 0)
  932.         (void) printf("%s ", constvol);
  933.     (void) printf("%s\n",type);
  934. }
  935.  
  936. /* Do the appropriate things for the "set" command. */
  937. void doset(opt)
  938. char *opt;
  939. {
  940.     if (strcmp(opt, "create") == 0)
  941.     { MkProgramFlag = 1; }
  942.     else if (strcmp(opt, "nocreate") == 0)
  943.     { MkProgramFlag = 0; }
  944.     else if (strcmp(opt, "interactive") == 0)
  945.     { Interactive = 1; }
  946.     else if (strcmp(opt, "nointeractive") == 0)
  947.     { Interactive = 0; OnATty = 0; }
  948.     else if (strcmp(opt, "ritchie") == 0)
  949.     { CplusplusFlag=0; RitchieFlag=1; PreANSIFlag=0; }
  950.     else if (strcmp(opt, "preansi") == 0)
  951.     { CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=1; }
  952.     else if (strcmp(opt, "ansi") == 0)
  953.     { CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=0; }
  954.     else if (strcmp(opt, "cplusplus") == 0)
  955.     { CplusplusFlag=1; RitchieFlag=0; PreANSIFlag=0; }
  956. #ifdef dodebug
  957.     else if (strcmp(opt, "debug") == 0)
  958.     { DebugFlag = 1; }
  959.     else if (strcmp(opt, "nodebug") == 0)
  960.     { DebugFlag = 0; }
  961. #endif /* dodebug */
  962. #ifdef doyydebug
  963.     else if (strcmp(opt, "yydebug") == 0)
  964.     { yydebug = 1; }
  965.     else if (strcmp(opt, "noyydebug") == 0)
  966.     { yydebug = 0; }
  967. #endif /* doyydebug */
  968.     else
  969.     {
  970.     if ((strcmp(opt, unknown_name) != 0) &&
  971.         (strcmp(opt, "options") != 0))
  972.         (void) printf("Unknown set option: '%s'\n", opt);
  973.  
  974.     (void) printf("Valid set options (and command line equivalents) are:\n");
  975.     (void) printf("\toptions\n");
  976.     (void) printf("\tcreate (-c), nocreate\n");
  977.     (void) printf("\tinteractive (-i), nointeractive\n");
  978.     (void) printf("\tritchie (-r), preansi (-p), ansi (-a) or cplusplus (-+)\n");
  979. #ifdef dodebug
  980.     (void) printf("\tdebug (-d), nodebug\n");
  981. #endif /* dodebug */
  982. #ifdef doyydebug
  983.     (void) printf("\tyydebug (-D), noyydebug\n");
  984. #endif /* doyydebug */
  985.  
  986.     (void) printf("\nCurrent set values are:\n");
  987.     (void) printf("\t%screate\n", MkProgramFlag ? "   " : " no");
  988.     (void) printf("\t%sinteractive\n",
  989.         (OnATty || Interactive) ? "   " : " no");
  990.     if (RitchieFlag)
  991.         (void) printf("\t   ritchie\n");
  992.     else
  993.         (void) printf("\t(noritchie)\n");
  994.     if (PreANSIFlag)
  995.         (void) printf("\t   preansi\n");
  996.     else
  997.         (void) printf("\t(nopreansi)\n");
  998.     if (!RitchieFlag && !PreANSIFlag && !CplusplusFlag)
  999.         (void) printf("\t   ansi\n");
  1000.     else
  1001.         (void) printf("\t(noansi)\n");
  1002.     if (CplusplusFlag)
  1003.         (void) printf("\t   cplusplus\n");
  1004.     else
  1005.         (void) printf("\t(nocplusplus)\n");
  1006. #ifdef dodebug
  1007.     (void) printf("\t%sdebug\n", DebugFlag ? "   " : " no");
  1008. #endif /* dodebug */
  1009. #ifdef doyydebug
  1010.     (void) printf("\t%syydebug\n", yydebug ? "   " : " no");
  1011. #endif /* doyydebug */
  1012.     }
  1013. }
  1014.  
  1015. void versions()
  1016. {
  1017.     (void) printf("Version:\n\t%s\n\t%s\n\t%s\n",
  1018.     cdeclsccsid, cdgramsccsid, cdlexsccsid);
  1019.     exit(0);
  1020. }
  1021.  
  1022. int main(argc, argv)
  1023. char **argv;
  1024. {
  1025.     int c, ret = 0;
  1026.  
  1027.     setprogname(argv[0]);
  1028. #ifdef DOS
  1029.     if (strcmp(progname, "cppdecl") == 0)
  1030. #else
  1031.     if (strcmp(progname, "c++decl") == 0)
  1032. #endif /* DOS */
  1033.     CplusplusFlag = 1;
  1034.  
  1035.     while ((c = getopt(argc, argv, "cirpa+dDV")) != EOF)
  1036.     switch (c)
  1037.         {
  1038.         case 'c': MkProgramFlag=1; break;
  1039.         case 'i': Interactive=1; break;
  1040.  
  1041.         /* The following are mutually exclusive. */
  1042.         /* Only the last one set prevails. */
  1043.         case 'r': CplusplusFlag=0; RitchieFlag=1; PreANSIFlag=0; break;
  1044.         case 'p': CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=1; break;
  1045.         case 'a': CplusplusFlag=0; RitchieFlag=0; PreANSIFlag=0; break;
  1046.         case '+': CplusplusFlag=1; RitchieFlag=0; PreANSIFlag=0; break;
  1047.  
  1048. #ifdef dodebug
  1049.         case 'd': DebugFlag=1; break;
  1050. #endif /* dodebug */
  1051. #ifdef doyydebug
  1052.         case 'D': yydebug=1; break;
  1053. #endif /* doyydebug */
  1054.         case 'V': versions(); break;
  1055.         case '?': usage(); break;
  1056.         }
  1057.  
  1058.     /* Run down the list of arguments, parsing each one. */
  1059.  
  1060.     /* Use standard input if no file names or "-" is found. */
  1061.     if (optind == argc)
  1062.     ret += dostdin();
  1063.  
  1064.     /* If called as explain, declare or cast, or first */
  1065.     /* argument is one of those, use the command line */
  1066.     /* as the input. */
  1067.     else if (namedkeyword(argv[optind]))
  1068.     ret += dotmpfile(argc, argv);
  1069.  
  1070.     else
  1071.     ret += dofileargs(argc, argv);
  1072.  
  1073.     exit(ret);
  1074.     /* NOTREACHED */
  1075. }
  1076. SHAR_EOF
  1077. cat << \SHAR_EOF > cdgram.y
  1078. %{
  1079. /* Yacc grammar for ANSI and C++ cdecl. */
  1080. /* The output of this file is included */
  1081. /* into the C file cdecl.c. */
  1082. char cdgramsccsid[] = "@(#)cdgram.y    2.2 3/30/88";
  1083. %}
  1084.  
  1085. %union {
  1086.     char *dynstr;
  1087.     struct {
  1088.         char *left;
  1089.         char *right;
  1090.         char *type;
  1091.     } halves;
  1092. }
  1093.  
  1094. %token ARRAY AS CAST COMMA DECLARE DOUBLECOLON EXPLAIN FUNCTION
  1095. %token HELP INTO OF MEMBER POINTER REFERENCE RETURNING SET TO
  1096. %token <dynstr> CHAR CLASS CONSTVOLATILE DOUBLE ENUM FLOAT INT LONG NAME
  1097. %token <dynstr> NUMBER SHORT SIGNED STRUCT UNION UNSIGNED VOID
  1098. %token <dynstr> AUTO EXTERN REGISTER STATIC
  1099. %type <dynstr> adecllist adims c_type cast castlist cdecl cdecl1 cdims
  1100. %type <dynstr> constvol_list ClassStruct mod_list mod_list1 modifier
  1101. %type <dynstr> opt_constvol_list optNAME opt_storage storage StrClaUniEnum
  1102. %type <dynstr> tname type
  1103. %type <halves> adecl
  1104.  
  1105. %start prog
  1106.  
  1107. %%
  1108. prog        : /* empty */
  1109.         | prog stmt
  1110.             {
  1111.             prompt();
  1112.             prev = 0;
  1113.             }
  1114.         ;
  1115.  
  1116. stmt        : HELP NL
  1117.             {
  1118.             Debug((stderr, "stmt: help\n"));
  1119.             dohelp();
  1120.             }
  1121.  
  1122.         | DECLARE NAME AS opt_storage adecl NL
  1123.             {
  1124.             Debug((stderr, "stmt: DECLARE NAME AS opt_storage adecl\n"));
  1125.             Debug((stderr, "\tNAME='%s'\n", $2));
  1126.             Debug((stderr, "\topt_storage='%s'\n", $4));
  1127.             Debug((stderr, "\tacdecl.left='%s'\n", $5.left));
  1128.             Debug((stderr, "\tacdecl.right='%s'\n", $5.right));
  1129.             Debug((stderr, "\tacdecl.type='%s'\n", $5.type));
  1130.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1131.             dodeclare($2, $4, $5.left, $5.right, $5.type);
  1132.             }
  1133.  
  1134.         | DECLARE opt_storage adecl NL
  1135.             {
  1136.             Debug((stderr, "stmt: DECLARE opt_storage adecl\n"));
  1137.             Debug((stderr, "\topt_storage='%s'\n", $2));
  1138.             Debug((stderr, "\tacdecl.left='%s'\n", $3.left));
  1139.             Debug((stderr, "\tacdecl.right='%s'\n", $3.right));
  1140.             Debug((stderr, "\tacdecl.type='%s'\n", $3.type));
  1141.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1142.             dodeclare(NullCP, $2, $3.left, $3.right, $3.type);
  1143.             }
  1144.  
  1145.         | CAST NAME INTO adecl NL
  1146.             {
  1147.             Debug((stderr, "stmt: CAST NAME AS adecl\n"));
  1148.             Debug((stderr, "\tNAME='%s'\n", $2));
  1149.             Debug((stderr, "\tacdecl.left='%s'\n", $4.left));
  1150.             Debug((stderr, "\tacdecl.right='%s'\n", $4.right));
  1151.             Debug((stderr, "\tacdecl.type='%s'\n", $4.type));
  1152.             docast($2, $4.left, $4.right, $4.type);
  1153.             }
  1154.  
  1155.         | CAST adecl NL
  1156.             {
  1157.             Debug((stderr, "stmt: CAST adecl\n"));
  1158.             Debug((stderr, "\tacdecl.left='%s'\n", $2.left));
  1159.             Debug((stderr, "\tacdecl.right='%s'\n", $2.right));
  1160.             Debug((stderr, "\tacdecl.type='%s'\n", $2.type));
  1161.             docast(NullCP, $2.left, $2.right, $2.type);
  1162.             }
  1163.  
  1164.         | EXPLAIN opt_storage opt_constvol_list type cdecl NL
  1165.             {
  1166.             Debug((stderr, "stmt: EXPLAIN opt_storage opt_constvol_list type cdecl\n"));
  1167.             Debug((stderr, "\topt_storage='%s'\n", $2));
  1168.             Debug((stderr, "\topt_constvol_list='%s'\n", $3));
  1169.             Debug((stderr, "\ttype='%s'\n", $4));
  1170.             Debug((stderr, "\tcdecl='%s'\n", $5));
  1171.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1172.             dodexplain($2, $3, $4, $5);
  1173.             }
  1174.  
  1175.         | EXPLAIN storage opt_constvol_list cdecl NL
  1176.             {
  1177.             Debug((stderr, "stmt: EXPLAIN storage opt_constvol_list cdecl\n"));
  1178.             Debug((stderr, "\tstorage='%s'\n", $2));
  1179.             Debug((stderr, "\topt_constvol_list='%s'\n", $3));
  1180.             Debug((stderr, "\tcdecl='%s'\n", $4));
  1181.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1182.             dodexplain($2, $3, NullCP, $4);
  1183.             }
  1184.  
  1185.         | EXPLAIN opt_storage constvol_list cdecl NL
  1186.             {
  1187.             Debug((stderr, "stmt: EXPLAIN opt_storage constvol_list cdecl\n"));
  1188.             Debug((stderr, "\topt_storage='%s'\n", $2));
  1189.             Debug((stderr, "\tconstvol_list='%s'\n", $3));
  1190.             Debug((stderr, "\tcdecl='%s'\n", $4));
  1191.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1192.             dodexplain($2, $3, NullCP, $4);
  1193.             }
  1194.  
  1195.         | EXPLAIN '(' opt_constvol_list type cast ')' optNAME NL
  1196.             {
  1197.             Debug((stderr, "stmt: EXPLAIN ( opt_constvol_list type cast ) optNAME\n"));
  1198.             Debug((stderr, "\topt_constvol_list='%s'\n", $3));
  1199.             Debug((stderr, "\ttype='%s'\n", $4));
  1200.             Debug((stderr, "\tcast='%s'\n", $5));
  1201.             Debug((stderr, "\tNAME='%s'\n", $7));
  1202.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1203.             docexplain($3, $4, $5, $7);
  1204.             }
  1205.  
  1206.         | SET optNAME NL
  1207.             {
  1208.             Debug((stderr, "stmt: SET optNAME\n"));
  1209.             Debug((stderr, "\toptNAME='%s'\n", $2));
  1210.             doset($2);
  1211.             }
  1212.  
  1213.         | NL
  1214.         | error NL
  1215.             {
  1216.             yyerrok;
  1217.             }
  1218.         ;
  1219.  
  1220. NL        : '\n'
  1221.             {
  1222.             doprompt();
  1223.             }
  1224.         | ';'
  1225.             {
  1226.             noprompt();
  1227.             }
  1228.         ;
  1229.  
  1230. optNAME        : NAME
  1231.             {
  1232.             Debug((stderr, "optNAME: NAME\n"));
  1233.             Debug((stderr, "\tNAME='%s'\n", $1));
  1234.             $$ = $1;
  1235.             }
  1236.  
  1237.         | /* empty */
  1238.             {
  1239.             Debug((stderr, "optNAME: EMPTY\n"));
  1240.             $$ = ds(unknown_name);
  1241.             }
  1242.         ;
  1243.  
  1244. cdecl        : cdecl1
  1245.         | '*' opt_constvol_list cdecl
  1246.             {
  1247.             Debug((stderr, "cdecl: * opt_constvol_list cdecl\n"));
  1248.             Debug((stderr, "\topt_constvol_list='%s'\n", $2));
  1249.             Debug((stderr, "\tcdecl='%s'\n", $3));
  1250.             $$ = cat($3,$2,ds(strlen($2)?" pointer to ":"pointer to "),NullCP);
  1251.             prev = 'p';
  1252.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1253.             }
  1254.  
  1255.         | NAME DOUBLECOLON '*' cdecl
  1256.             {
  1257.             Debug((stderr, "cdecl: NAME DOUBLECOLON '*' cdecl\n"));
  1258.             Debug((stderr, "\tNAME='%s'\n", $1));
  1259.             Debug((stderr, "\tcdecl='%s'\n", $4));
  1260.             if (!CplusplusFlag)
  1261.                 unsupp("pointer to member of class", NullCP);
  1262.             $$ = cat($4,ds("pointer to member of class "),$1,ds(" "),NullCP);
  1263.             prev = 'p';
  1264.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1265.             }
  1266.  
  1267.         | '&' opt_constvol_list cdecl
  1268.             {
  1269.             Debug((stderr, "cdecl: & opt_constvol_list cdecl\n"));
  1270.             Debug((stderr, "\topt_constvol_list='%s'\n", $2));
  1271.             Debug((stderr, "\tcdecl='%s'\n", $3));
  1272.             if (!CplusplusFlag)
  1273.                 unsupp("reference", NullCP);
  1274.             $$ = cat($3,$2,ds(strlen($2)?" reference to ":"reference to "),NullCP);
  1275.             prev = 'r';
  1276.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1277.             }
  1278.         ;
  1279.  
  1280. cdecl1        : cdecl1 '(' ')'
  1281.             {
  1282.             Debug((stderr, "cdecl1: cdecl1()\n"));
  1283.             Debug((stderr, "\tcdecl1='%s'\n", $1));
  1284.             $$ = cat($1,ds("function returning "),NullCP);
  1285.             prev = 'f';
  1286.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1287.             }
  1288.  
  1289.         | cdecl1 '(' castlist ')'
  1290.             {
  1291.             Debug((stderr, "cdecl1: cdecl1(castlist)\n"));
  1292.             Debug((stderr, "\tcdecl1='%s'\n", $1));
  1293.             Debug((stderr, "\tcastlist='%s'\n", $3));
  1294.             $$ = cat($1, ds("function ("),
  1295.                   $3, ds(") returning "), NullCP);
  1296.             prev = 'f';
  1297.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1298.             }
  1299.  
  1300.         | cdecl1 cdims
  1301.             {
  1302.             Debug((stderr, "cdecl1: cdecl1 cdims\n"));
  1303.             Debug((stderr, "\tcdecl1='%s'\n", $1));
  1304.             Debug((stderr, "\tcdims='%s'\n", $2));
  1305.             $$ = cat($1,ds("array "),$2,NullCP);
  1306.             prev = 'a';
  1307.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1308.             }
  1309.  
  1310.         | '(' cdecl ')'
  1311.             {
  1312.             Debug((stderr, "cdecl1: (cdecl)\n"));
  1313.             Debug((stderr, "\tcdecl='%s'\n", $2));
  1314.             $$ = $2;
  1315.             /* prev = prev; */
  1316.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1317.             }
  1318.  
  1319.         | NAME
  1320.             {
  1321.             Debug((stderr, "cdecl1: NAME\n"));
  1322.             Debug((stderr, "\tNAME='%s'\n", $1));
  1323.             savedname = $1;
  1324.             $$ = ds("");
  1325.             prev = 'n';
  1326.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1327.             }
  1328.         ;
  1329.  
  1330. castlist    : castlist COMMA castlist
  1331.             {
  1332.             Debug((stderr, "castlist: castlist1, castlist2\n"));
  1333.             Debug((stderr, "\tcastlist1='%s'\n", $1));
  1334.             Debug((stderr, "\tcastlist2='%s'\n", $3));
  1335.             $$ = cat($1, ds(", "), $3, NullCP);
  1336.             }
  1337.  
  1338.         | opt_constvol_list type cast
  1339.             {
  1340.             Debug((stderr, "castlist: opt_constvol_list type cast\n"));
  1341.             Debug((stderr, "\topt_constvol_list='%s'\n", $1));
  1342.             Debug((stderr, "\ttype='%s'\n", $2));
  1343.             Debug((stderr, "\tcast='%s'\n", $3));
  1344.             $$ = cat($3, $1, ds(strlen($1) ? " " : ""), $2, NullCP);
  1345.             }
  1346.  
  1347.         | NAME
  1348.             {
  1349.             $$ = $1;
  1350.             }
  1351.         ;
  1352.  
  1353. adecllist    : /* empty */
  1354.             {
  1355.             Debug((stderr, "adecllist: EMPTY\n"));
  1356.             $$ = ds("");
  1357.             }
  1358.  
  1359.         | adecllist COMMA adecllist
  1360.             {
  1361.             Debug((stderr, "adecllist: adecllist1, adecllist2\n"));
  1362.             Debug((stderr, "\tadecllist1='%s'\n", $1));
  1363.             Debug((stderr, "\tadecllist2='%s'\n", $3));
  1364.             $$ = cat($1, ds(", "), $3, NullCP);
  1365.             }
  1366.  
  1367.         | NAME
  1368.             {
  1369.             Debug((stderr, "adecllist: NAME\n"));
  1370.             Debug((stderr, "\tNAME='%s'\n", $1));
  1371.             $$ = $1;
  1372.             }
  1373.  
  1374.         | adecl
  1375.             {
  1376.             Debug((stderr, "adecllist: adecl\n"));
  1377.             Debug((stderr, "\tadecl.left='%s'\n", $1.left));
  1378.             Debug((stderr, "\tadecl.right='%s'\n", $1.right));
  1379.             Debug((stderr, "\tadecl.type='%s'\n", $1.type));
  1380.             $$ = cat($1.type, ds(" "), $1.left, $1.right, NullCP);
  1381.             }
  1382.  
  1383.         | NAME AS adecl
  1384.             {
  1385.             Debug((stderr, "adecllist: NAME AS adecl\n"));
  1386.             Debug((stderr, "\tNAME='%s'\n", $1));
  1387.             Debug((stderr, "\tadecl.left='%s'\n", $3.left));
  1388.             Debug((stderr, "\tadecl.right='%s'\n", $3.right));
  1389.             Debug((stderr, "\tadecl.type='%s'\n", $3.type));
  1390.             $$ = cat($3.type, ds(" "), $3.left, $1, $3.right, NullCP);
  1391.             }
  1392.         ;
  1393.  
  1394. cast        : /* empty */
  1395.             {
  1396.             Debug((stderr, "cast: EMPTY\n"));
  1397.             $$ = ds("");
  1398.             /* prev = prev; */
  1399.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1400.             }
  1401.  
  1402.         | '(' ')'
  1403.             {
  1404.             Debug((stderr, "cast: ()\n"));
  1405.             $$ = ds("function returning ");
  1406.             prev = 'f';
  1407.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1408.             }
  1409.  
  1410.         | '(' cast ')' '(' ')'
  1411.             {
  1412.             Debug((stderr, "cast: (cast)()\n"));
  1413.             Debug((stderr, "\tcast='%s'\n", $2));
  1414.             $$ = cat($2,ds("function returning "),NullCP);
  1415.             prev = 'f';
  1416.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1417.             }
  1418.  
  1419.         | '(' cast ')' '(' castlist ')'
  1420.             {
  1421.             Debug((stderr, "cast: (cast)(castlist)\n"));
  1422.             Debug((stderr, "\tcast='%s'\n", $2));
  1423.             Debug((stderr, "\tcastlist='%s'\n", $5));
  1424.             $$ = cat($2,ds("function ("),$5,ds(") returning "),NullCP);
  1425.             prev = 'f';
  1426.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1427.             }
  1428.  
  1429.         | '(' cast ')'
  1430.             {
  1431.             Debug((stderr, "cast: (cast)\n"));
  1432.             Debug((stderr, "\tcast='%s'\n", $2));
  1433.             $$ = $2;
  1434.             /* prev = prev; */
  1435.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1436.             }
  1437.  
  1438.         | NAME DOUBLECOLON '*' cast
  1439.             {
  1440.             Debug((stderr, "cast: NAME::*cast\n"));
  1441.             Debug((stderr, "\tcast='%s'\n", $4));
  1442.             if (!CplusplusFlag)
  1443.                 unsupp("pointer to member of class", NullCP);
  1444.             $$ = cat($4,ds("pointer to member of class "),$1,ds(" "),NullCP);
  1445.             prev = 'p';
  1446.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1447.             }
  1448.  
  1449.         | '*' cast
  1450.             {
  1451.             Debug((stderr, "cast: *cast\n"));
  1452.             Debug((stderr, "\tcast='%s'\n", $2));
  1453.             $$ = cat($2,ds("pointer to "),NullCP);
  1454.             prev = 'p';
  1455.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1456.             }
  1457.  
  1458.         | '&' cast
  1459.             {
  1460.             Debug((stderr, "cast: &cast\n"));
  1461.             Debug((stderr, "\tcast='%s'\n", $2));
  1462.             if (!CplusplusFlag)
  1463.                 unsupp("reference", NullCP);
  1464.             $$ = cat($2,ds("reference to "),NullCP);
  1465.             prev = 'r';
  1466.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1467.             }
  1468.  
  1469.         | cast cdims
  1470.             {
  1471.             Debug((stderr, "cast: cast cdims\n"));
  1472.             Debug((stderr, "\tcast='%s'\n", $1));
  1473.             Debug((stderr, "\tcdims='%s'\n", $2));
  1474.             $$ = cat($1,ds("array "),$2,NullCP);
  1475.             prev = 'a';
  1476.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1477.             }
  1478.         ;
  1479.  
  1480. cdims        : '[' ']'
  1481.             {
  1482.             Debug((stderr, "cdims: []\n"));
  1483.             $$ = ds("of ");
  1484.             }
  1485.  
  1486.         | '[' NUMBER ']'
  1487.             {
  1488.             Debug((stderr, "cdims: [NUMBER]\n"));
  1489.             Debug((stderr, "\tNUMBER='%s'\n", $2));
  1490.             $$ = cat($2,ds(" of "),NullCP);
  1491.             }
  1492.         ;
  1493.  
  1494. adecl        : FUNCTION RETURNING adecl
  1495.             {
  1496.             Debug((stderr, "adecl: FUNCTION RETURNING adecl\n"));
  1497.             Debug((stderr, "\tadecl.left='%s'\n", $3.left));
  1498.             Debug((stderr, "\tadecl.right='%s'\n", $3.right));
  1499.             Debug((stderr, "\tadecl.type='%s'\n", $3.type));
  1500.             if (prev == 'f')
  1501.                 unsupp("Function returning function",
  1502.                        "function returning pointer to function");
  1503.             else if (prev=='A' || prev=='a')
  1504.                 unsupp("Function returning array",
  1505.                        "function returning pointer");
  1506.             $$.left = $3.left;
  1507.             $$.right = cat(ds("()"),$3.right,NullCP);
  1508.             $$.type = $3.type;
  1509.             prev = 'f';
  1510.             Debug((stderr, "\n\tadecl now =\n"));
  1511.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1512.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1513.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1514.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1515.             }
  1516.  
  1517.         | FUNCTION '(' adecllist ')' RETURNING adecl
  1518.             {
  1519.             Debug((stderr, "adecl: FUNCTION (adecllist) RETURNING adecl\n"));
  1520.             Debug((stderr, "\tadecllist='%s'\n", $3));
  1521.             Debug((stderr, "\tadecl.left='%s'\n", $6.left));
  1522.             Debug((stderr, "\tadecl.right='%s'\n", $6.right));
  1523.             Debug((stderr, "\tadecl.type='%s'\n", $6.type));
  1524.             if (prev == 'f')
  1525.                 unsupp("Function returning function",
  1526.                        "function returning pointer to function");
  1527.             else if (prev=='A' || prev=='a')
  1528.                 unsupp("Function returning array",
  1529.                        "function returning pointer");
  1530.             $$.left = $6.left;
  1531.             $$.right = cat(ds("("),$3,ds(")"),$6.right,NullCP);
  1532.             $$.type = $6.type;
  1533.             prev = 'f';
  1534.             Debug((stderr, "\n\tadecl now =\n"));
  1535.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1536.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1537.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1538.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1539.             }
  1540.  
  1541.         | ARRAY adims OF adecl
  1542.             {
  1543.             Debug((stderr, "adecl: ARRAY adims OF adecl\n"));
  1544.             Debug((stderr, "\tadims='%s'\n", $2));
  1545.             Debug((stderr, "\tadecl.left='%s'\n", $4.left));
  1546.             Debug((stderr, "\tadecl.right='%s'\n", $4.right));
  1547.             Debug((stderr, "\tadecl.type='%s'\n", $4.type));
  1548.             if (prev == 'f')
  1549.                 unsupp("Array of function",
  1550.                        "array of pointer to function");
  1551.             else if (prev == 'a')
  1552.                 unsupp("Inner array of unspecified size",
  1553.                        "array of pointer");
  1554.             else if (prev == 'v')
  1555.                 unsupp("Array of void",
  1556.                        "pointer to void");
  1557.             if (arbdims)
  1558.                 prev = 'a';
  1559.             else
  1560.                 prev = 'A';
  1561.             $$.left = $4.left;
  1562.             $$.right = cat($2,$4.right,NullCP);
  1563.             $$.type = $4.type;
  1564.             Debug((stderr, "\n\tadecl now =\n"));
  1565.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1566.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1567.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1568.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1569.             }
  1570.  
  1571.         | opt_constvol_list POINTER TO adecl
  1572.             {
  1573.             char *op = "", *cp = "", *sp = "";
  1574.  
  1575.             Debug((stderr, "adecl: opt_constvol_list POINTER TO adecl\n"));
  1576.             Debug((stderr, "\topt_constvol_list='%s'\n", $1));
  1577.             Debug((stderr, "\tadecl.left='%s'\n", $4.left));
  1578.             Debug((stderr, "\tadecl.right='%s'\n", $4.right));
  1579.             Debug((stderr, "\tadecl.type='%s'\n", $4.type));
  1580.             if (prev == 'a')
  1581.                 unsupp("Pointer to array of unspecified dimension",
  1582.                        "pointer to object");
  1583.             if (prev=='a' || prev=='A' || prev=='f') {
  1584.                 op = "(";
  1585.                 cp = ")";
  1586.             }
  1587.             if (strlen($1) != 0)
  1588.                 sp = " ";
  1589.             $$.left = cat($4.left,ds(op),ds("*"),
  1590.                        ds(sp),$1,ds(sp),NullCP);
  1591.             $$.right = cat(ds(cp),$4.right,NullCP);
  1592.             $$.type = $4.type;
  1593.             prev = 'p';
  1594.             Debug((stderr, "\n\tadecl now =\n"));
  1595.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1596.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1597.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1598.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1599.             }
  1600.  
  1601.         | opt_constvol_list POINTER TO MEMBER OF ClassStruct NAME adecl
  1602.             {
  1603.             char *op = "", *cp = "", *sp = "";
  1604.  
  1605.             Debug((stderr, "adecl: opt_constvol_list POINTER TO MEMBER OF ClassStruct NAME adecl\n"));
  1606.             Debug((stderr, "\topt_constvol_list='%s'\n", $1));
  1607.             Debug((stderr, "\tClassStruct='%s'\n", $6));
  1608.             Debug((stderr, "\tNAME='%s'\n", $7));
  1609.             Debug((stderr, "\tadecl.left='%s'\n", $8.left));
  1610.             Debug((stderr, "\tadecl.right='%s'\n", $8.right));
  1611.             Debug((stderr, "\tadecl.type='%s'\n", $8.type));
  1612.             if (!CplusplusFlag)
  1613.                 unsupp("pointer to member of class", NullCP);
  1614.             if (prev == 'a')
  1615.                 unsupp("Pointer to array of unspecified dimension",
  1616.                        "pointer to object");
  1617.             if (prev=='a' || prev=='A' || prev=='f') {
  1618.                 op = "(";
  1619.                 cp = ")";
  1620.             }
  1621.             if (strlen($1) != 0)
  1622.                 sp = " ";
  1623.             $$.left = cat($8.left,ds(op),$7,ds("::*"),
  1624.                       ds(sp),$1,ds(sp),NullCP);
  1625.             $$.right = cat(ds(cp),$8.right,NullCP);
  1626.             $$.type = $8.type;
  1627.             prev = 'p';
  1628.             Debug((stderr, "\n\tadecl now =\n"));
  1629.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1630.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1631.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1632.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1633.             }
  1634.  
  1635.         | opt_constvol_list REFERENCE TO adecl
  1636.             {
  1637.             char *op = "", *cp = "", *sp = "";
  1638.  
  1639.             Debug((stderr, "adecl: opt_constvol_list REFERENCE TO adecl\n"));
  1640.             Debug((stderr, "\topt_constvol_list='%s'\n", $1));
  1641.             Debug((stderr, "\tadecl.left='%s'\n", $4.left));
  1642.             Debug((stderr, "\tadecl.right='%s'\n", $4.right));
  1643.             Debug((stderr, "\tadecl.type='%s'\n", $4.type));
  1644.             if (!CplusplusFlag)
  1645.                 unsupp("reference", NullCP);
  1646.             if (prev == 'v')
  1647.                 unsupp("Reference to void",
  1648.                        "pointer to void");
  1649.             else if (prev == 'a')
  1650.                 unsupp("Reference to array of unspecified dimension",
  1651.                        "reference to object");
  1652.             if (prev=='a' || prev=='A' || prev=='f') {
  1653.                 op = "(";
  1654.                 cp = ")";
  1655.             }
  1656.             if (strlen($1) != 0)
  1657.                 sp = " ";
  1658.             $$.left = cat($4.left,ds(op),ds("&"),
  1659.                        ds(sp),$1,ds(sp),NullCP);
  1660.             $$.right = cat(ds(cp),$4.right,NullCP);
  1661.             $$.type = $4.type;
  1662.             prev = 'r';
  1663.             Debug((stderr, "\n\tadecl now =\n"));
  1664.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1665.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1666.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1667.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1668.             }
  1669.  
  1670.         | opt_constvol_list type
  1671.             {
  1672.             Debug((stderr, "adecl: opt_constvol_list type\n"));
  1673.             Debug((stderr, "\topt_constvol_list='%s'\n", $1));
  1674.             Debug((stderr, "\ttype='%s'\n", $2));
  1675.             $$.left = ds("");
  1676.             $$.right = ds("");
  1677.             $$.type = cat($1,ds(strlen($1)?" ":""),$2,NullCP);
  1678.             if (strcmp($2, "void") == 0)
  1679.                 prev = 'v';
  1680.             else if ((strncmp($2, "struct", 6) == 0) ||
  1681.                      (strncmp($2, "class", 5) == 0))
  1682.                 prev = 's';
  1683.             else
  1684.                 prev = 't';
  1685.             Debug((stderr, "\n\tadecl now =\n"));
  1686.             Debug((stderr, "\t\tadecl.left='%s'\n", $$.left));
  1687.             Debug((stderr, "\t\tadecl.right='%s'\n", $$.right));
  1688.             Debug((stderr, "\t\tadecl.type='%s'\n", $$.type));
  1689.             Debug((stderr, "\tprev = '%s'\n", visible(prev)));
  1690.             }
  1691.         ;
  1692.  
  1693. adims        : /* empty */
  1694.             {
  1695.             Debug((stderr, "adims: EMPTY\n"));
  1696.             arbdims = 1;
  1697.             $$ = ds("[]");
  1698.             }
  1699.  
  1700.         | NUMBER
  1701.             {
  1702.             Debug((stderr, "adims: NUMBER\n"));
  1703.             Debug((stderr, "\tNUMBER='%s'\n", $1));
  1704.             arbdims = 0;
  1705.             $$ = cat(ds("["),$1,ds("]"),NullCP);
  1706.             }
  1707.         ;
  1708.  
  1709. type        : tinit c_type
  1710.             {
  1711.             Debug((stderr, "type: tinit c_type\n"));
  1712.             Debug((stderr, "\ttinit=''\n"));
  1713.             Debug((stderr, "\tc_type='%s'\n", $2));
  1714.             mbcheck();
  1715.             $$ = $2;
  1716.             }
  1717.         ;
  1718.  
  1719. tinit        : /* empty */
  1720.             {
  1721.             Debug((stderr, "tinit: EMPTY\n"));
  1722.             modbits = 0;
  1723.             }
  1724.         ;
  1725.  
  1726. c_type        : mod_list
  1727.             {
  1728.             Debug((stderr, "c_type: mod_list\n"));
  1729.             Debug((stderr, "\tmod_list='%s'\n", $1));
  1730.             $$ = $1;
  1731.             }
  1732.  
  1733.         | tname
  1734.             {
  1735.             Debug((stderr, "c_type: tname\n"));
  1736.             Debug((stderr, "\ttname='%s'\n", $1));
  1737.             $$ = $1;
  1738.             }
  1739.  
  1740.         | mod_list tname
  1741.             {
  1742.             Debug((stderr, "c_type: mod_list tname\n"));
  1743.             Debug((stderr, "\tmod_list='%s'\n", $1));
  1744.             Debug((stderr, "\ttname='%s'\n", $2));
  1745.             $$ = cat($1,ds(" "),$2,NullCP);
  1746.             }
  1747.  
  1748.         | StrClaUniEnum NAME
  1749.             {
  1750.             Debug((stderr, "c_type: StrClaUniEnum NAME\n"));
  1751.             Debug((stderr, "\tStrClaUniEnum='%s'\n", $1));
  1752.             Debug((stderr, "\tNAME='%s'\n", $2));
  1753.             $$ = cat($1,ds(" "),$2,NullCP);
  1754.             }
  1755.         ;
  1756.  
  1757. StrClaUniEnum    : ClassStruct
  1758.         | ENUM
  1759.         | UNION
  1760.             {
  1761.             $$ = $1;
  1762.             }
  1763.         ;
  1764.  
  1765. ClassStruct    : STRUCT
  1766.         | CLASS
  1767.             {
  1768.             $$ = $1;
  1769.             }
  1770.         ;
  1771.  
  1772. tname        : INT
  1773.             {
  1774.             Debug((stderr, "tname: INT\n"));
  1775.             Debug((stderr, "\tINT='%s'\n", $1));
  1776.             modbits |= MB_INT; $$ = $1;
  1777.             }
  1778.  
  1779.         | CHAR
  1780.             {
  1781.             Debug((stderr, "tname: CHAR\n"));
  1782.             Debug((stderr, "\tCHAR='%s'\n", $1));
  1783.             modbits |= MB_CHAR; $$ = $1;
  1784.             }
  1785.  
  1786.         | FLOAT
  1787.             {
  1788.             Debug((stderr, "tname: FLOAT\n"));
  1789.             Debug((stderr, "\tFLOAT='%s'\n", $1));
  1790.             modbits |= MB_FLOAT; $$ = $1;
  1791.             }
  1792.  
  1793.         | DOUBLE
  1794.             {
  1795.             Debug((stderr, "tname: DOUBLE\n"));
  1796.             Debug((stderr, "\tDOUBLE='%s'\n", $1));
  1797.             modbits |= MB_DOUBLE; $$ = $1;
  1798.             }
  1799.  
  1800.         | VOID
  1801.             {
  1802.             Debug((stderr, "tname: VOID\n"));
  1803.             Debug((stderr, "\tVOID='%s'\n", $1));
  1804.             modbits |= MB_VOID; $$ = $1;
  1805.             }
  1806.         ;
  1807.  
  1808. mod_list    : modifier mod_list1
  1809.             {
  1810.             Debug((stderr, "mod_list: modifier mod_list1\n"));
  1811.             Debug((stderr, "\tmodifier='%s'\n", $1));
  1812.             Debug((stderr, "\tmod_list1='%s'\n", $2));
  1813.             $$ = cat($1,ds(" "),$2,NullCP);
  1814.             }
  1815.  
  1816.         | modifier
  1817.             {
  1818.             Debug((stderr, "mod_list: modifier\n"));
  1819.             Debug((stderr, "\tmodifier='%s'\n", $1));
  1820.             $$ = $1;
  1821.             }
  1822.         ;
  1823.  
  1824. mod_list1    : mod_list
  1825.             {
  1826.             Debug((stderr, "mod_list1: mod_list\n"));
  1827.             Debug((stderr, "\tmod_list='%s'\n", $1));
  1828.             $$ = $1;
  1829.             }
  1830.  
  1831.         | CONSTVOLATILE
  1832.             {
  1833.             Debug((stderr, "mod_list1: CONSTVOLATILE\n"));
  1834.             Debug((stderr, "\tCONSTVOLATILE='%s'\n", $1));
  1835.             if (PreANSIFlag)
  1836.                 notsupported(" (Pre-ANSI Compiler)", $1, NullCP);
  1837.             else if (RitchieFlag)
  1838.                 notsupported(" (Ritchie Compiler)", $1, NullCP);
  1839.             else if ((strcmp($1, "noalias") == 0) && CplusplusFlag)
  1840.                 unsupp($1, NullCP);
  1841.             $$ = $1;
  1842.             }
  1843.         ;
  1844.  
  1845. modifier    : UNSIGNED
  1846.             {
  1847.             Debug((stderr, "modifier: UNSIGNED\n"));
  1848.             Debug((stderr, "\tUNSIGNED='%s'\n", $1));
  1849.             modbits |= MB_UNSIGNED; $$ = $1;
  1850.             }
  1851.  
  1852.         | SIGNED
  1853.             {
  1854.             Debug((stderr, "modifier: SIGNED\n"));
  1855.             Debug((stderr, "\tSIGNED='%s'\n", $1));
  1856.             modbits |= MB_SIGNED; $$ = $1;
  1857.             }
  1858.  
  1859.         | LONG
  1860.             {
  1861.             Debug((stderr, "modifier: LONG\n"));
  1862.             Debug((stderr, "\tLONG='%s'\n", $1));
  1863.             modbits |= MB_LONG; $$ = $1;
  1864.             }
  1865.  
  1866.         | SHORT
  1867.             {
  1868.             Debug((stderr, "modifier: SHORT\n"));
  1869.             Debug((stderr, "\tSHORT='%s'\n", $1));
  1870.             modbits |= MB_SHORT; $$ = $1;
  1871.             }
  1872.         ;
  1873.  
  1874. opt_constvol_list: CONSTVOLATILE opt_constvol_list
  1875.             {
  1876.             Debug((stderr, "opt_constvol_list: CONSTVOLATILE opt_constvol_list\n"));
  1877.             Debug((stderr, "\tCONSTVOLATILE='%s'\n", $1));
  1878.             Debug((stderr, "\topt_constvol_list='%s'\n", $2));
  1879.             if (PreANSIFlag)
  1880.                 notsupported(" (Pre-ANSI Compiler)", $1, NullCP);
  1881.             else if (RitchieFlag)
  1882.                 notsupported(" (Ritchie Compiler)", $1, NullCP);
  1883.             else if ((strcmp($1, "noalias") == 0) && CplusplusFlag)
  1884.                 unsupp($1, NullCP);
  1885.             $$ = cat($1,ds(strlen($2) ? " " : ""),$2,NullCP);
  1886.             }
  1887.  
  1888.         | /* empty */
  1889.             {
  1890.             Debug((stderr, "opt_constvol_list: EMPTY\n"));
  1891.             $$ = ds("");
  1892.             }
  1893.         ;
  1894.  
  1895. constvol_list: CONSTVOLATILE opt_constvol_list
  1896.             {
  1897.             Debug((stderr, "constvol_list: CONSTVOLATILE opt_constvol_list\n"));
  1898.             Debug((stderr, "\tCONSTVOLATILE='%s'\n", $1));
  1899.             Debug((stderr, "\topt_constvol_list='%s'\n", $2));
  1900.             if (PreANSIFlag)
  1901.                 notsupported(" (Pre-ANSI Compiler)", $1, NullCP);
  1902.             else if (RitchieFlag)
  1903.                 notsupported(" (Ritchie Compiler)", $1, NullCP);
  1904.             else if ((strcmp($1, "noalias") == 0) && CplusplusFlag)
  1905.                 unsupp($1, NullCP);
  1906.             $$ = cat($1,ds(strlen($2) ? " " : ""),$2,NullCP);
  1907.             }
  1908.         ;
  1909.  
  1910. storage        : AUTO
  1911.         | EXTERN
  1912.         | REGISTER
  1913.         | STATIC
  1914.             {
  1915.             Debug((stderr, "storage: AUTO,EXTERN,STATIC,REGISTER (%s)\n", $1));
  1916.             $$ = $1;
  1917.             }
  1918.         ;
  1919.  
  1920. opt_storage    : storage
  1921.             {
  1922.             Debug((stderr, "opt_storage: storage=%s\n", $1));
  1923.             $$ = $1;
  1924.             }
  1925.  
  1926.         | /* empty */
  1927.             {
  1928.             Debug((stderr, "opt_storage: EMPTY\n"));
  1929.             $$ = ds("");
  1930.             }
  1931.         ;
  1932. %%
  1933. SHAR_EOF
  1934. cat << \SHAR_EOF > cdecl.1
  1935. '\" @(#)cdecl.1    2.4 3/30/88
  1936. .TH CDECL 1
  1937. .SH NAME
  1938. cdecl, c++decl \- Compose C and C++ type declarations
  1939. .SH SYNOPSIS
  1940. .B cdecl
  1941. [\-a | \-+ | \-p | \-r]
  1942. [\-cidDV]
  1943. .br
  1944. .RS .5i
  1945. .RI [[ files
  1946. \&...] |
  1947. .B explain
  1948. \&... |
  1949. .B declare
  1950. \&... |
  1951. .B cast
  1952. \&... |
  1953. .B set
  1954. \&... |
  1955. .B help
  1956. \&... |
  1957. .B ?
  1958. \&... ]
  1959. .RE
  1960. .br
  1961. .B c++decl
  1962. [\-a | \-+ | \-p | \-r]
  1963. [\-cidDV]
  1964. .br
  1965. .RS .5i
  1966. .RI [[ files
  1967. \&...] |
  1968. .B explain
  1969. \&... |
  1970. .B declare
  1971. \&... |
  1972. .B cast
  1973. \&... |
  1974. .B set
  1975. \&... |
  1976. .B help
  1977. \&... |
  1978. .B ?
  1979. \&... ]
  1980. .RE
  1981. .br
  1982. .B explain
  1983. \&...
  1984. .br
  1985. .B declare
  1986. \&...
  1987. .br
  1988. .B cast
  1989. \&...
  1990. .SH DESCRIPTION
  1991. .I Cdecl
  1992. (and
  1993. .I c++decl )
  1994. is a program for encoding and decoding C (C++) type-declarations.
  1995. The C language (the default for 
  1996. .I cdecl ,
  1997. or with the
  1998. .B \-a
  1999. option) is based on the (draft proposed) X3J11 ANSI
  2000. Standard;
  2001. optionally, the C language may be based on the pre-ANSI definition defined by
  2002. Kernighan & Ritchie's 
  2003. .I "The C Programming Language"
  2004. book (the
  2005. .B \-p
  2006. option is used), or
  2007. the C language defined by the Ritchie PDP-11 C compiler (the
  2008. .B \-r
  2009. option is used).
  2010. The C++ language (the default for
  2011. .I c++decl ,
  2012. or with the
  2013. .B \-+
  2014. option) is based on Stroustrup's
  2015. .IR "The C++ Programming Language" ,
  2016. plus the version 2.0 additions to the language.
  2017. .PP
  2018. .I Cdecl
  2019. reads the named files for statements in the language described below.
  2020. A transformation is made from that language to C (C++) or pseudo-English.
  2021. The results of this transformation are written on standard output.
  2022. If no files are named, or a filename of ``\-'' is encountered, standard input
  2023. will be read.
  2024. If standard input is coming from a terminal, (or the
  2025. .B \-i
  2026. option is used), a prompt will be written to the terminal before each line.
  2027. If
  2028. .I cdecl
  2029. is invoked as 
  2030. .IR explain ,
  2031. .IR declare
  2032. or
  2033. .IR cast ,
  2034. or the first argument is one of the commands discussed below, the argument
  2035. list will be interpreted according to the grammar shown below instead of as
  2036. file names.
  2037. .PP
  2038. You can use
  2039. .I cdecl
  2040. as you create a C program with an editor like vi(1) or emacs(1).
  2041. You simply type in the pseudo-English version of the declaration and apply
  2042. .I cdecl
  2043. as a filter to the line.
  2044. (In vi(1), type ``!!cdecl<cr>''.)
  2045. .PP
  2046. If the 
  2047. .I "create program"
  2048. option
  2049. .B \-c
  2050. is used, the output will include semi-colons after variable declarations and
  2051. curly brace pairs after function declarations.
  2052. .PP
  2053. The
  2054. .B \-V
  2055. option will print out the version numbers of the files used to create the
  2056. process.
  2057. If the source is compiled with debugging information turned on, the
  2058. .B \-d
  2059. option will enable it to be output.
  2060. If the source is compiled with YACC debugging information turned on, the
  2061. .B \-D
  2062. option will enable it to be output.
  2063. .SH "COMMAND LANGUAGE"
  2064. There are six statements in the language.
  2065. The
  2066. .I "declare"
  2067. statement composes a C type-declaration from a verbose description.
  2068. The
  2069. .I "cast"
  2070. statement composes a C type-cast as might appear in an expression.
  2071. The
  2072. .I "explain"
  2073. statement decodes a C type-declaration or cast, producing a verbose
  2074. description.
  2075. The
  2076. .I "help"
  2077. (or
  2078. .IR ? )
  2079. statement provides a help message.
  2080. The
  2081. .I "quit"
  2082. (or
  2083. .IR "exit" )
  2084. statement (or the end of file) exits the program.
  2085. The
  2086. .I "set"
  2087. statement allows the command line options to be set interactively.
  2088. Each statement is separated by a semi-colon or a newline.
  2089. .PP
  2090. The following grammar describes the language.
  2091. In the grammar, words in "<>" are non-terminals,
  2092. bare lower-case words are terminals that stand for themselves.
  2093. Bare upper-case words are other lexical tokens:
  2094. NOTHING means the empty string;
  2095. NAME means a C identifier;
  2096. NUMBER means a string of decimal digits; and
  2097. NL means the new-line or semi-colon characters.
  2098. .PP
  2099. Some synonyms are permitted during a declaration:
  2100. character \(-> char,
  2101. constant \(-> const,
  2102. enumeration \(-> enum,
  2103. func \(-> function,
  2104. integer \(-> int,
  2105. ptr \(-> pointer,
  2106. ref \(-> reference,
  2107. ret \(-> returning,
  2108. structure \(-> struct,
  2109. and
  2110. vector \(-> array.
  2111. .PP
  2112. .nf
  2113. .ft CW
  2114. .ta .5i 1.5i
  2115.     <program>    ::= NOTHING
  2116.         | <program> <stmt> NL
  2117.     <stmt>    ::= NOTHING
  2118.         | declare NAME as <adecl>
  2119.         | declare <adecl>
  2120.         | cast NAME into <adecl>
  2121.         | cast <adecl>
  2122.         | explain <optstorage> <ptrmodlist> <type> <cdecl>
  2123.         | explain <storage> <ptrmodlist> <cdecl>
  2124.         | explain ( <ptrmodlist> <type> <cast> ) optional-NAME
  2125.         | set <options>
  2126.         | help | ?
  2127.         | quit
  2128.         | exit
  2129.     <adecl>    ::= array of <adecl>
  2130.         | array NUMBER of <adecl>
  2131.         | function returning <adecl>
  2132.         | function ( <adecl-list> ) returning <adecl>
  2133.         | <ptrmodlist> pointer to <adecl>
  2134.         | <ptrmodlist> pointer to member of class NAME <adecl>
  2135.         | <ptrmodlist> reference to <adecl>
  2136.         | <ptrmodlist> <type>
  2137.     <cdecl>    ::= <cdecl1>
  2138.         | * <ptrmodlist> <cdecl>
  2139.         | NAME :: * <cdecl>
  2140.         | & <ptrmodlist> <cdecl>
  2141.     <cdecl1>    ::= <cdecl1> ( )
  2142.         | <cdecl1> ( <castlist> )
  2143.         | <cdecl1> [ ]
  2144.         | <cdecl1> [ NUMBER ]
  2145.         | ( <cdecl> )
  2146.         | NAME
  2147.     <cast>    ::= NOTHING
  2148.         | ( )
  2149.         | ( <cast> ) ( )
  2150.         | ( <cast> ) ( <castlist> )
  2151.         | ( <cast> )
  2152.         | NAME :: * <cast>
  2153.         | * <cast>
  2154.         | & <cast>
  2155.         | <cast> [ ]
  2156.         | <cast> [ NUMBER ]
  2157.     <type>    ::= <typename> | <modlist>
  2158.         | <modlist> <typename>
  2159.         | struct NAME | union NAME | enum NAME | class NAME
  2160.     <castlist>    ::= <castlist> , <castlist>
  2161.         | <ptrmodlist> <type> <cast>
  2162.         | <name>
  2163.     <adecllist>    ::= <adecllist> , <adecllist>
  2164.         | NOTHING
  2165.         | <name>
  2166.         | <adecl>
  2167.         | <name> as <adecl>
  2168.     <typename>    ::= int | char | double | float | void
  2169.     <modlist>    ::= <modifier> | <modlist> <modifier>
  2170.     <modifier>    ::= short | long | unsigned | signed | <ptrmod>
  2171.     <ptrmodlist>    ::= <ptrmod> <ptrmodlist> | NOTHING
  2172.     <ptrmod>    ::= const | volatile | noalias
  2173.     <storage>    ::= auto | extern | register | auto
  2174.     <optstorage>    ::= NOTHING | <storage>
  2175.     <options>    ::= NOTHING | <options>
  2176.         | create | nocreate
  2177.         | interactive | nointeractive
  2178.         | ritchie | preansi | ansi | cplusplus
  2179.         | debug | nodebug | yydebug | noyydebug
  2180. .ft P
  2181. .fi
  2182. .SH EXAMPLES
  2183. .de Ex
  2184. .    PP
  2185. .    RS .5i
  2186. ..
  2187. .de Ee
  2188. .    RE
  2189. .    PP
  2190. ..
  2191. To declare an array of pointers to functions like malloc(3), do
  2192. .Ex
  2193. declare fptab as array of pointer to function returning pointer to char
  2194. .Ee
  2195. The result of this command is
  2196. .Ex
  2197. char *(*fptab[])()
  2198. .Ee
  2199. When you see this declaration in someone else's code, you
  2200. can make sense out of it by doing
  2201. .Ex
  2202. explain char *(*fptab[])()
  2203. .Ee
  2204. The proper declaration for signal(2), ignoring function prototypes, is easily
  2205. described in
  2206. .IR cdecl 's
  2207. language:
  2208. .Ex
  2209. declare signal as function returning pointer to function returning void
  2210. .Ee
  2211. which produces
  2212. .Ex
  2213. void (*signal())()
  2214. .Ee
  2215. The function declaration that results has two sets of empty parentheses.
  2216. The author of such a function might wonder where to put the parameters:
  2217. .Ex
  2218. declare signal as function (arg1,arg2) returning pointer to function returning
  2219. void
  2220. .Ee
  2221. provides the following solution (when run with the
  2222. .I \-c
  2223. option):
  2224. .Ex
  2225. void (*signal(arg1,arg2))()
  2226. {
  2227. }
  2228. .Ee
  2229. If we want to add in the function prototypes, the function prototype for a
  2230. function such as _exit(2) would be declared with:
  2231. .Ex
  2232. declare _exit as function (retvalue as int) returning void
  2233. .Ee
  2234. giving
  2235. .Ex
  2236. void _exit(int retvalue)
  2237. {
  2238. }
  2239. .Ee
  2240. As a more complex example using function prototypes, signal(2) could be fully
  2241. defined as:
  2242. .Ex
  2243. declare signal as function(x as int, y as pointer to function(int)
  2244. returning void) returning pointer to function(int) returning void
  2245. .Ee
  2246. giving (with \-c)
  2247. .Ex
  2248. void (*signal(int x, void (*y)(int )))(int )
  2249. {
  2250. }
  2251. .Ee
  2252. .I Cdecl
  2253. can help figure out the where to put the "const" and "volatile" modifiers
  2254. in declarations, thus
  2255. .Ex
  2256. declare foo as pointer to const int
  2257. .Ee
  2258. gives
  2259. .Ex
  2260. const int *foo
  2261. .Ee
  2262. while
  2263. .Ex
  2264. declare foo as const pointer to int
  2265. .Ee
  2266. gives
  2267. .Ex
  2268. int * const foo
  2269. .Ee
  2270. .I C++decl
  2271. can help with declaring references, thus
  2272. .Ex
  2273. declare x as reference to pointer to character
  2274. .Ee
  2275. gives
  2276. .Ex
  2277. char *&x
  2278. .Ee
  2279. .I C++decl
  2280. can help with pointers to member of classes, thus
  2281. declaring a pointer to an integer member of a class X with
  2282. .Ex
  2283. declare foo as pointer to member of class X int
  2284. .Ee
  2285. gives
  2286. .Ex
  2287. int X::*foo
  2288. .Ee
  2289. and
  2290. .Ex
  2291. declare foo as pointer to member of class X function (arg1, arg2) returning
  2292. pointer to class Y
  2293. .Ee
  2294. gives
  2295. .Ex
  2296. class Y *(X::*foo)(arg1, arg2)
  2297. .Ee
  2298. .SH DIAGNOSTICS
  2299. The declare, cast and explain statements try to point out constructions that
  2300. are not supported in C.
  2301. In some cases, a guess is made as to what was really intended.
  2302. In these cases, the C result is a toy declaration whose semantics will work
  2303. only in Algol-68.
  2304. The list of unsupported C constructs is dependent on which version of the C
  2305. language is being used (see the ANSI, pre-ANSI, and Ritchie options).
  2306. The set of supported C++ constructs is a superset of the ANSI set, with the
  2307. exception of the
  2308. .B noalias
  2309. keyword.
  2310. .SH "SEE ALSO"
  2311. (draft proposed) ANSI National Standard X3J11
  2312. .sp
  2313. \(sc8.4 of the C Reference Manual within
  2314. .I "The C Programming Language"
  2315. by B. Kernighan & D. Ritchie.
  2316. .sp
  2317. \(sc8 of the C++ Reference Manual within
  2318. .I "The C++ Programming Language"
  2319. by B. Stroustrup.
  2320. .SH CAVEATS
  2321. The pseudo-English syntax is excessively verbose.
  2322. .PP
  2323. There is a wealth of semantic checking that isn't being done.
  2324. .PP
  2325. .I Cdecl's
  2326. scope is intentionally small.
  2327. It doesn't help you figure out initializations.
  2328. It expects storage classes to be at the beginning of a declaration,
  2329. followed by the the const, volatile and noalias modifiers, followed by the
  2330. type of the variable.
  2331. .I Cdecl
  2332. doesn't know anything about variable length argument lists.
  2333. (This includes the ``\f(CW,...\fP'' syntax.)
  2334. .PP
  2335. .I Cdecl
  2336. thinks all the declarations you utter are going to be used as external
  2337. definitions.
  2338. Some declaration contexts in C allow more flexibility than this.
  2339. An example of this is:
  2340. .Ex
  2341. declare argv as array of array of char
  2342. .Ee
  2343. where
  2344. .I cdecl
  2345. responds with
  2346. .Ex
  2347. .nf
  2348. Warning: Unsupported in C -- 'Inner array of unspecified size'
  2349.         (maybe you mean "array of pointer")
  2350. char argv[][]
  2351. .fi
  2352. .Ee
  2353. .PP
  2354. Tentative support for the
  2355. .I noalias
  2356. keyword has been put in because it is in the current ANSI specifications.
  2357. SHAR_EOF
  2358. #    End of shell archive
  2359. exit 0
  2360. -- 
  2361. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2362. Have five nice days.
  2363.